package org.garden.id.generator.segment;

import org.apache.commons.lang3.StringUtils;
import org.garden.id.generator.segment.service.IdGenerator;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

public class Id {

    private static volatile Id id = Id.instance();

    private DataSource dataSource;

    private Integer retry = 3;

    private Integer loadPercent = 30;

    private static final ConcurrentHashMap<String, IdGenerator> generators = new ConcurrentHashMap<>();

    public static Long nextId(String type) {
        if(type == null) {
            throw new IllegalArgumentException("type is null");
        }
        return id.getIdGenerator(type).nextId();
    }

    private IdGenerator getIdGenerator(String type) {
        if (generators.containsKey(type)) {
            return generators.get(type);
        }
        synchronized (this) {
            if (generators.containsKey(type)) {
                return generators.get(type);
            }
            IdGenerator idGenerator = new IdGenerator(type, dataSource, retry, loadPercent);
            generators.put(type, idGenerator);
            return idGenerator;
        }
    }

    public static Id instance() {
        if (id == null) {
            synchronized (Id.class) {
                if (id == null) {
                    id = new Id();
                    Properties properties = loadProperties();
                    String username = properties.getProperty("id.datasource.username");
                    String password = properties.getProperty("id.datasource.password");
                    String url = properties.getProperty("id.datasource.url");
                    String driverClass = properties.getProperty("id.datasource.driver-class-name");
                    if (StringUtils.isNotBlank(properties.getProperty("id.retry"))) {
                        id.retry = Integer.parseInt(properties.getProperty("id.retry"));
                    }
                    if (StringUtils.isNotBlank(properties.getProperty("id.load-percent"))) {
                        id.loadPercent = Integer.parseInt(properties.getProperty("id.load-percent"));
                    }
                    DriverManagerDataSource dataSource = new DriverManagerDataSource();
                    dataSource.setUsername(username);
                    dataSource.setPassword(password);
                    dataSource.setUrl(url);
                    dataSource.setDriverClassName(driverClass);
                    id.dataSource = dataSource;
                }
            }
        }
        return id;
    }

    private static Properties loadProperties() {
        Properties props = new Properties();
        InputStreamReader in = null;
        try {
            in = new InputStreamReader(Id.class.getClassLoader().getResourceAsStream("id.properties"), "UTF-8");
            props.load(in);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        } finally {
            if(in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return props;
    }
}
